#include "gtest.h"
#include "open_ringbuffer.h"

oprb_ringbuffer ringbuffer;

TEST(oprb_writeline, case_null_str)
{
    EXPECT_EQ(oprb_writeline(""), OPRB_FAILED);
}

TEST(oprb_writeline, case_normal)
{
    char *str = "[2023-07-10 14:22:01][BOOT][Warn]: UBoot failed,compare key hash failed.\n";
    int  str_len = strlen(str);
    EXPECT_EQ(oprb_writeline(str), str_len);
    ringbuffer = oprb_get_ringbuffer();
    EXPECT_EQ(ringbuffer.log_item_reader, 0);
    EXPECT_EQ(ringbuffer.log_item_writer, 1);
    EXPECT_EQ(ringbuffer.log_item_used_len, 1);
    EXPECT_EQ(ringbuffer.log_item[0].str_len, str_len);
    EXPECT_EQ(ringbuffer.str_buffer_reader,0);
    EXPECT_EQ(ringbuffer.str_buffer_writer, str_len);
    EXPECT_EQ(ringbuffer.str_buffer_used_len, str_len);
}

TEST(oprb_writeline, case_item_full)
{
    char *str = "haha\n";
    for(int i=0; i< OPRB_LOG_ITEM_MAX_LEN -1; i++)
    {
        EXPECT_EQ(oprb_writeline(str), strlen(str));
    }
    EXPECT_EQ(oprb_writeline(str), OPRB_LOG_ITEM_FULL);
}

TEST(oprb_writeline, case_str_buffer_full)
{
    char out_str[1000];
    char *str = "[2023-07-10 14:22:01][BOOT][Warn]: UBoot failed,compare key hash failed.\n";
    int str_len = strlen(str);
    ringbuffer = oprb_get_ringbuffer();
    for(int i=0; i< ringbuffer.log_item_used_len; i++)
    {
        EXPECT_GT(oprb_readline(out_str, 1000),0);
    }

    int items = OPRB_STR_BUFFER_MAX_LEN / str_len;
    for (int i = 0; i < items; i++)
    {
        EXPECT_EQ(oprb_writeline(str), str_len);
    }

    ringbuffer = oprb_get_ringbuffer();

    EXPECT_EQ(oprb_writeline(str), OPRB_STR_BUFFER_FULL);

}

TEST(oprb_writeline, case_item_bound)
{
    char out_str[1000];
    char *str = "[2023-07-10 14:22:01][BOOT][Warn]: UBoot failed,compare key hash failed.\n";
    int str_len = strlen(str);
    ringbuffer = oprb_get_ringbuffer();
    for(int i=0; i< ringbuffer.log_item_used_len; i++)
    {
        EXPECT_GT(oprb_readline(out_str, 1000),0);
    }
    ringbuffer = oprb_get_ringbuffer();
    for (int i = ringbuffer.log_item_writer; i < OPRB_LOG_ITEM_MAX_LEN; i++)
    {
        EXPECT_EQ(oprb_writeline(str), str_len);
    }
    ringbuffer = oprb_get_ringbuffer();
    EXPECT_EQ(ringbuffer.log_item_writer, 0);
}

TEST(oprb_writeline, case_str_buffer_bound)
{
    ringbuffer = oprb_get_ringbuffer();    
    char *str = "[2023-07-10 14:22:01][BOOT][Warn]: UBoot failed,compare key hash failed.\n";
    int str_len = strlen(str);
    int items = (OPRB_STR_BUFFER_MAX_LEN - ringbuffer.str_buffer_writer)/str_len;
    int str_buff_used_len0 = ringbuffer.str_buffer_used_len;
    int str_buff_writer0 = ringbuffer.str_buffer_writer;
    for (int i = 0; i < items; i++)
    {
        EXPECT_EQ(oprb_writeline(str), str_len);
    }
    ringbuffer = oprb_get_ringbuffer();
    int str_buff_used_len1 = ringbuffer.str_buffer_used_len;
    EXPECT_EQ(str_buff_used_len1, str_buff_used_len0 + items * str_len);
    EXPECT_EQ(oprb_writeline(str), str_len);
    ringbuffer = oprb_get_ringbuffer();
    EXPECT_EQ(ringbuffer.str_buffer_writer, str_len - (OPRB_STR_BUFFER_MAX_LEN - str_buff_writer0 -items * str_len));
    EXPECT_EQ(ringbuffer.str_buffer_used_len, str_buff_used_len1 + str_len);
}

TEST(oprb_readline, case_empty)
{
    char out_str[1000];
    ringbuffer = oprb_get_ringbuffer();
    for(int i=0; i< ringbuffer.log_item_used_len; i++)
    {
        EXPECT_GT(oprb_readline(out_str, 1000),0);
    }
    EXPECT_EQ(oprb_readline(out_str, 1000),OPRB_LOG_ITEM_EMPTY);
}

TEST(oprb_readline, case_readbuff_not_enough)
{
    char out_str[10];
    char *str = "[2023-07-10 14:22:01][BOOT][Warn]: UBoot failed,compare key hash failed.\n";
    int str_len = strlen(str);
    EXPECT_EQ(oprb_writeline(str), str_len);
    EXPECT_EQ(oprb_readline(out_str, 10),OPRB_LOG_LEN_OVER_RECV_BUFF_LEN);
}

TEST(oprb_readline, case_normal)
{
    char out_str[1000];
    char *str = "[2023-07-10 14:22:01][BOOT][Warn]: UBoot failed,compare key hash failed.\n";
    int str_len = strlen(str);
    ringbuffer = oprb_get_ringbuffer();
    for(int i=0; i< ringbuffer.log_item_used_len; i++)
    {
        EXPECT_GT(oprb_readline(out_str, 1000),0);
    }
    EXPECT_EQ(oprb_writeline(str), str_len);
    EXPECT_EQ(oprb_readline(out_str, 1000), str_len);
}

TEST(oprb_readline, case_item_bound)
{
    char out_str[1000];
    char *str = "haha.\n";
    int str_len = strlen(str);
    ringbuffer = oprb_get_ringbuffer();    

    for (int i = 0; i <OPRB_LOG_ITEM_MAX_LEN - ringbuffer.log_item_writer; i++)
    {
        EXPECT_EQ(oprb_writeline(str), str_len);
    }

    ringbuffer = oprb_get_ringbuffer();    

    for (int i = 0; i < OPRB_LOG_ITEM_MAX_LEN - ringbuffer.log_item_reader; i++)
    {
        EXPECT_GT(oprb_readline(out_str, 1000),0);
    }
    ringbuffer = oprb_get_ringbuffer();    
    EXPECT_EQ(ringbuffer.log_item_reader, 0);
}

TEST(oprb_readline, case_strbuff_bound)
{
    char out_str[1000];
    char *str = "[2023-07-10 14:22:01][BOOT][Warn]: UBoot failed,compare key hash failed.\n";
    int str_len = strlen(str);
    ringbuffer = oprb_get_ringbuffer();
    int items = (OPRB_STR_BUFFER_MAX_LEN - ringbuffer.str_buffer_writer)/str_len;
    for (int i = 0; i < items; i++)
    {
        EXPECT_EQ(oprb_writeline(str), str_len);
    }
    EXPECT_EQ(oprb_writeline(str), str_len);

    ringbuffer = oprb_get_ringbuffer();

    for (int i = 0; i < ringbuffer.log_item_used_len; i++)
    {
        EXPECT_GT(oprb_readline(out_str, 1000), 0);
    }
    ringbuffer = oprb_get_ringbuffer();
    EXPECT_EQ(ringbuffer.str_buffer_reader, ringbuffer.str_buffer_writer);    
}

int main(int argc, char** argv)
{
    std::cout << "Hello, open ringbuffer utest!\n";
    // testing::GTEST_FLAG(output) = "xml:";
    testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}
